
// des_one.cpp: implementation of the des_one class.
//
//////////////////////////////////////////////////////////////////////


#include "DesOne.h"
#include "string.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

des_one::des_one()
{

}

des_one::~des_one()
{

}
/*******************************************************************************
*函数名称：Des_SetKey
*功能描述：生成子密钥
*输入参数：@uint8_t Key[8]     用户密钥
*
*输出参数：无
*返回参数：无
*其    他：生成子密钥只要在做数据加密或者解密之前执行一次即可，生成的子密钥被放在RAM中，只有
           更新了密钥之后才有必要重新生成子密钥。
           生成的子密钥大小为 768 字节。
*******************************************************************************/
void des_one::Des_SetKey(uint8_t Key[])
{
    int i;
    static bool K[64], *KL = &K[0], *KR = &K[28];

    ByteToBit(K, (const char*)Key, 64);   //转换为二进制

    Transform(K, K, PC1_Table, 56);   //64比特的密钥K，经过PC-1后，生成56比特的串。

    //生成16个子密钥
    for(i=0; i<16; i++)
    {
        //循环左移，合并
        RotateL(KL, 28, LOOP_Table[i]);
        RotateL(KR, 28, LOOP_Table[i]);
        Transform(SubKey[i], K, PC2_Table, 48);
     }
}

/*******************************************************************************
*函数名称：Des_Run
*功能描述：数据进行 DES 加密或解密
*输入参数：
*          @uint8_t     In[IN]       输入数据
*          @bool        Type:
*                               ENCRYPT     加密
*                               DECRYPT     解密
*输出参数：@uint8_t    Out[OUT]   输出数据
*返回参数：无
*其    他：DES 每次只能对8个字节进行加密或解密。
*******************************************************************************/
void des_one::Des_Run(uint8_t *Out, uint8_t *In, bool Type)
{
    int i;
    static bool M[64], tmp[32], *Li = &M[0], *Ri = &M[32];

    //转换为64位的数据块
    ByteToBit(M, (const char*)In, 64);

    //IP置换 （初始）
    Transform(M, M, IP_Table, 64);

    //该比特串被分为32位的L0和32位的R0两部分。

    if( Type == ENCRYPT )
    {
        //16轮置换
        for(i=0; i<16; i++)
        {
            memcpy(tmp, Ri, 32);

            // R[i] = L[i-1] xor f(R[i-1], K[i])
            F_func(Ri, SubKey[i]);

            // 2.4.6 Exclusive-or the resulting value with L[i-1].
            // R[I]=P XOR L[I-1]
            Xor(Ri, Li, 32);

            // L[i] = R[i-1]
            memcpy(Li, tmp, 32);

        }
    }
    else
    {
        // 如果解密则反转子密钥顺序
        for(i=15; i>=0; i--)
        {
            memcpy(tmp, Li, 32);
            F_func(Li, SubKey[i]);
            Xor(Li, Ri, 32);
            memcpy(Ri, tmp, 32);
        }
    }

    //R16与L16合并成64位的比特串。R16一定要排在L16前面。R16与L16合并后成的比特串，经过置换IP-1后所得的比特串就是密文。
    Transform(M, M, IPR_Table, 64);

     BitToByte((char*)Out, (const bool *)M, 64);
}


void des_one::F_func(bool In[32], const bool Ki[48])
{
    static bool MR[48];

    //输入Ri-1(32比特)经过变换E后，膨胀为48比特
    Transform(MR, In, E_Table, 48);

    //异或
    Xor(MR, Ki, 48);

    //膨胀后的比特串分为8组，每组6比特。各组经过各自的S盒后，又变为4比特(具体过程见后)，合并后又成为32比特。
    S_func(In, MR);

    //该32比特经过P变换后，输出的比特串才是32比特的f (Ri-1,Ki)。
     Transform(In, In, P_Table, 32);
}
void des_one::S_func(bool Out[32], const bool In[48])
{
     char j,m,n;

     //膨胀后的比特串分为8组，每组6比特。
     for(j=0; j<8; j++,In+=6,Out+=4)
     {
         //在其输入In[0],In[1],In[2],In[3],In[4],In[5]中，计算出m=In[0]*2+In[5], n=In[4]+In[3]*2+In[2]*4+In[1]*8，再从Sj表中查出m行，n列的值Smn。将Smn化为二进制，即得Si盒的输出。
         m = (In[0]<<1) + In[5];
         n = (In[1]<<3) + (In[2]<<2) + (In[3]<<1) + In[4];

         ByteToBit(Out, &S_Box[(int)j][(int)m][(int)n], 4);
     }
}

void des_one::Transform(bool *Out, bool *In, const char *Table, int len)
{
    int i;
    static bool tmp[256];
    for ( i = 0; i < len; i++)
    {
        tmp[i] = In[Table[i]-1];

    }
    memcpy(Out,tmp,len);
}

void des_one::Xor(bool *InA, const bool *InB, int len)
{
    int i;
    for ( i = 0; i < len; i++ )
    {
        InA[i] = InA[i]^InB[i];
    }
}
void des_one::RotateL(bool *In, int len, int loop)
{
    static bool tmp[256];            // Sample:  loop=2
    memcpy(tmp,In,loop);             // In=12345678 tmp=12
    memcpy(In,In+loop,len-loop);     // In=345678
    memcpy(In+len-loop,tmp,loop);    // In=34567812

}

// Sample:
// In = [0x01]
// Out = [0x01] [0x00] [0x00] [0x00] [0x00] [0x00] [0x00] [0x00]
void des_one::ByteToBit(bool *Out, const char *In, int bits)
{
    int i;
    // In[i]的第N位右移N位并和0x01按位"与"运算(N=1~8)
    for ( i = 0; i < bits; i++ )
    {
        if ((In[i/8] >> (i%8 ))& 1 > 0)
        {
            Out[i] = 1;
        }
        else
        {
            Out[i] = 0;
        }
    }
}
void des_one::BitToByte(char *Out, const bool *In, int bits)
{
    int i;
    memset(Out,0,(bits+7)/8);
    for ( i = 0; i < bits; i++)
    {
        Out[i/8] |= In[i] << (i%8);
    }
}

